grammar Mysql;

options {
    language = Java;
    output=AST;
}

@header {
package eu.lexoft.mygears;
}
@lexer::header {
package eu.lexoft.mygears;
}

@members {
    protected void mismatch(IntStream input, int ttype, BitSet follow)
        throws RecognitionException
    {
        throw new MismatchedTokenException(ttype, input);
    }

    public void recoverFromMismatchedSet(IntStream input,
                                         RecognitionException e,
                                         BitSet follow)
        throws RecognitionException
    {
        throw e;
    }
}

@rulecatch {
    catch (RecognitionException e) {
        throw e;
    }
}

prog:   (decl ';')+;

decl:   create_table;

create_table
    :   T_CREATE T_TEMPORARY? T_TABLE (T_IF T_NOT T_EXISTS)? varname table_definition;

table_definition
    :   '(' create_definition (',' create_definition)* ')';

create_definition
    :   varname column_definition; // TODO: dezvolta definitia

column_definition
    :   data_type 
        (
            (T_NOT? T_NULL) 
        |   (T_DEFAULT value) 
        |   T_AUTO_INCREMENT 
        |   (T_UNIQUE T_KEY | T_PRIMARY? T_KEY)
        |   (T_COMMENT String)
        )*
        /* add reference definition */
    ;

data_type
    :   T_BIT ('(' Number ')')?
    |   T_TINYINT ('(' Number ')')? (T_UNSIGNED)? (T_ZEROFILL)?
    |   T_SMALLINT ('(' Number ')')? (T_UNSIGNED)? (T_ZEROFILL)?
    |   T_MEDIUMINT ('(' Number ')')? (T_UNSIGNED)? (T_ZEROFILL)?
    |   T_INT ('(' Number ')')? (T_UNSIGNED)? (T_ZEROFILL)?
    |   T_INTEGER ('(' Number ')')? (T_UNSIGNED)? (T_ZEROFILL)?
    |   T_BIGINT ('(' Number ')')? (T_UNSIGNED)? (T_ZEROFILL)?
    |   T_REAL ('(' Number ',' Number ')')? (T_UNSIGNED)? (T_ZEROFILL)?
    |   T_DOUBLE ('(' Number ',' Number ')')? (T_UNSIGNED)? (T_ZEROFILL)?
    |   T_FLOAT ('(' Number ',' Number ')')? (T_UNSIGNED)? (T_ZEROFILL)?
    |   T_DECIMAL ( '(' Number (',' Number)? ')' )? (T_UNSIGNED)? (T_ZEROFILL)?
    |   T_NUMERIC ( '(' Number (',' Number)? ')' )? (T_UNSIGNED)? (T_ZEROFILL)?
    |   T_DATE
    |   T_TIME
    |   T_TIMESTAMP
    |   T_DATETIME
    |   T_YEAR
    |   T_CHAR ('(' Number ')')? 
        (T_CHARACTER T_SET character_set)? (T_COLLATE collation_name)?
    |   T_VARCHAR '(' Number ')'
        (T_CHARACTER T_SET character_set)? (T_COLLATE collation_name)?
    |   T_BINARY ('(' Number ')')?
    |   T_VARBINARY'(' Number ')'
    |   T_TINYBLOB
    |   T_BLOB
    |   T_MEDIUMBLOB
    |   T_LONGBLOB
    |   T_TINYTEXT (T_BINARY)?
        (T_CHARACTER T_SET character_set)? (T_COLLATE collation_name)?
    |   T_TEXT (T_BINARY)?
        (T_CHARACTER T_SET character_set)? (T_COLLATE collation_name)?
    |   T_MEDIUMTEXT (T_BINARY)?
        (T_CHARACTER T_SET character_set)? (T_COLLATE collation_name)?
    |   T_LONGTEXT (T_BINARY)?
        (T_CHARACTER T_SET character_set)? (T_COLLATE collation_name)?
    |   T_ENUM (String (',' String)*)
        (T_CHARACTER T_SET character_set)? (T_COLLATE collation_name)?
    |   T_SET (String (',' String)*)
        (T_CHARACTER T_SET character_set)? (T_COLLATE collation_name)?;

character_set
    :   ID | String;

collation_name
    :   ID | String;

value
    :   String | Number;

varname
    :   (ID | '`' ID '`');


// case-insensitive words
T_CREATE
    :   ('C'|'c') ('R'|'r') ('E'|'e') ('A'|'a') ('T'|'t') ('E'|'e');
T_TEMPORARY
    :   ('T'|'t') ('E'|'e') ('M'|'m') ('P'|'p') ('O'|'o') ('R'|'r') ('A'|'a') ('R'|'r') ('Y'|'y');
T_TABLE
    :   ('T'|'t') ('A'|'a') ('B'|'b') ('L'|'l') ('E'|'e');
T_IF    :   ('I'|'i') ('F'|'f');
T_NOT   :   ('N'|'n') ('O'|'o') ('T'|'t');
T_EXISTS
    :   ('E'|'e') ('X'|'x') ('I'|'i') ('S'|'s') ('T'|'t') ('S'|'s');
T_NULL  :   ('N'|'n') ('U'|'u') ('L'|'l') ('L'|'l');

T_DEFAULT
    :   ('D'|'d') ('E'|'e') ('F'|'f') ('A'|'a') ('U'|'u') ('L'|'l') ('T'|'t');

T_AUTO_INCREMENT
	:	('A'|'a') ('U'|'u') ('T'|'t') ('O'|'o') '_' 
        ('I'|'i') ('N'|'n') ('C'|'c') ('R'|'r') ('E'|'e') ('M'|'m') ('E'|'e') ('N'|'n') ('T'|'t');
T_UNIQUE
	:	('U'|'u') ('N'|'n') ('I'|'i') ('Q'|'q') ('U'|'u') ('E'|'e');
T_KEY	:	('K'|'k') ('E'|'e') ('Y'|'y');
T_PRIMARY
	:	('P'|'p') ('R'|'r') ('I'|'i') ('M'|'m') ('A'|'a') ('R'|'r') ('Y'|'y');
T_COMMENT
	:	('C'|'c') ('O'|'o') ('M'|'m') ('M'|'m') ('E'|'e') ('N'|'n') ('T'|'t');

T_BIT	:	('B'|'b') ('I'|'i') ('T'|'t');
T_TINYINT
	:	('T'|'t') ('I'|'i') ('N'|'n') ('Y'|'y') ('I'|'i') ('N'|'n') ('T'|'t');
T_SMALLINT
	:	('S'|'s') ('M'|'m') ('A'|'a') ('L'|'l') ('L'|'l') ('I'|'i') ('N'|'n') ('T'|'t');
T_MEDIUMINT
	:	('M'|'m') ('E'|'e') ('D'|'d') ('I'|'i') ('U'|'u') ('M'|'m') ('I'|'i') ('N'|'n') ('T'|'t');
T_INT	:	('I'|'i') ('N'|'n') ('T'|'t');
T_INTEGER
	:	('I'|'i') ('N'|'n') ('T'|'t') ('E'|'e') ('G'|'g') ('E'|'e') ('R'|'r');
T_BIGINT
	:	('B'|'b') ('I'|'i') ('G'|'g') ('I'|'i') ('N'|'n') ('T'|'t');
T_REAL	:	('R'|'r') ('E'|'e') ('A'|'a') ('L'|'l');
T_DOUBLE
	:	('D'|'d') ('O'|'o') ('U'|'u') ('B'|'b') ('L'|'l') ('E'|'e');
T_FLOAT
	:	('F'|'f') ('L'|'l') ('O'|'o') ('A'|'a') ('T'|'t');
T_DECIMAL
	:	('D'|'d') ('E'|'e') ('C'|'c') ('I'|'i') ('M'|'m') ('A'|'a') ('L'|'l');
T_NUMERIC
	:	('N'|'n') ('U'|'u') ('M'|'m') ('E'|'e') ('R'|'r') ('I'|'i') ('C'|'c');
T_DATE	:	('D'|'d') ('A'|'a') ('T'|'t') ('E'|'e');
T_TIME	:	('T'|'t') ('I'|'i') ('M'|'m') ('E'|'e');
T_TIMESTAMP
	:	('T'|'t') ('I'|'i') ('M'|'m') ('E'|'e') ('S'|'s') ('T'|'t') ('A'|'a') ('M'|'m') ('P'|'p');
T_DATETIME
	:	('D'|'d') ('A'|'a') ('T'|'t') ('E'|'e') ('T'|'t') ('I'|'i') ('M'|'m') ('E'|'e');
T_YEAR	
    :	('Y'|'y') ('E'|'e') ('A'|'a') ('R'|'r');
T_CHAR	
    :	('C'|'c') ('H'|'h') ('A'|'a') ('R'|'r');
T_CHARACTER
	:	('C'|'c') ('H'|'h') ('A'|'a') ('R'|'r') ('A'|'a') ('C'|'c') ('T'|'t') ('E'|'e') ('R'|'r');
T_SET	
    :	('S'|'s') ('E'|'e') ('T'|'t');
T_COLLATE
	:	('C'|'c') ('O'|'o') ('L'|'l') ('L'|'l') ('A'|'a') ('T'|'t') ('E'|'e');
T_VARCHAR
	:	('V'|'v') ('A'|'a') ('R'|'r') ('C'|'c') ('H'|'h') ('A'|'a') ('R'|'r');
T_BINARY
	:	('B'|'b') ('I'|'i') ('N'|'n') ('A'|'a') ('R'|'r') ('Y'|'y');
T_VARBINARY
	:	('V'|'v') ('A'|'a') ('R'|'r') ('B'|'b') ('I'|'i') ('N'|'n') ('A'|'a') ('R'|'r') ('Y'|'y');
T_TINYBLOB
	:	('T'|'t') ('I'|'i') ('N'|'n') ('Y'|'y') ('B'|'b') ('L'|'l') ('O'|'o') ('B'|'b');
T_BLOB	
    :	('B'|'b') ('L'|'l') ('O'|'o') ('B'|'b');
T_MEDIUMBLOB
	:	('M'|'m') ('E'|'e') ('D'|'d') ('I'|'i') ('U'|'u') ('M'|'m') ('B'|'b') ('L'|'l') ('O'|'o') ('B'|'b');
T_LONGBLOB
	:	('L'|'l') ('O'|'o') ('N'|'n') ('G'|'g') ('B'|'b') ('L'|'l') ('O'|'o') ('B'|'b');
T_TINYTEXT
	:	('T'|'t') ('I'|'i') ('N'|'n') ('Y'|'y') ('T'|'t') ('E'|'e') ('X'|'x') ('T'|'t');
T_TEXT	
    :	('T'|'t') ('E'|'e') ('X'|'x') ('T'|'t');
T_MEDIUMTEXT
	:	('M'|'m') ('E'|'e') ('D'|'d') ('I'|'i') ('U'|'u') ('M'|'m') ('T'|'t') ('E'|'e') ('X'|'x') ('T'|'t');
T_LONGTEXT
	:	('L'|'l') ('O'|'o') ('N'|'n') ('G'|'g') ('T'|'t') ('E'|'e') ('X'|'x') ('T'|'t');
T_ENUM	
    :	('E'|'e') ('N'|'n') ('U'|'u') ('M'|'m');
T_ZEROFILL	
    :	('Z'|'z') ('E'|'e') ('R'|'r') ('O'|'o') ('F'|'f') ('I'|'i') ('L'|'l') ('L'|'l');
T_UNSIGNED
	:	('U'|'u') ('N'|'n') ('S'|'s') ('I'|'i') ('G'|'g') ('N'|'n') ('E'|'e') ('D'|'d');

// other lexer rules
ID  :   ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*;

WS: (' '|'\n'|'\r'|'\t')+ {$channel=HIDDEN;} ; // ignore whitespace 

Number	: '-'? Digit+ ( '.' Digit+)?;

String
    : '"' (EscapeSequence | ~('\u0000'..'\u001f' | '\\' | '\"'))* '"'
    | '\'' (EscapeSequence | ~('\u0000'..'\u001f' | '\\' | '\''))* '\'';

fragment EscapeSequence
    :   '\\' (UnicodeEscape | 'b' | 't' | 'n' | 'f' | 'r' | '\"' | '\''| '\\');

fragment UnicodeEscape
	:   'u' HexDigit HexDigit HexDigit HexDigit
	;

fragment HexDigit
    :   '0'..'9' | 'A'..'F' | 'a'..'f';

fragment Digit 
    :   '0'..'9';

